package cate.game.play.skill.effect;


import cate.common.table.d.*;
import cate.game.attr.FightAttr;
import cate.game.play.buff.BuffHandler;
import cate.game.play.fighter.DamageResult;
import cate.game.play.fighter.Fighter;
import cate.game.play.fighter.FighterPerformance;
import cate.game.play.fighter.HealResult;
import cate.game.play.proce.action.ctx.SkillActionCtx;
import cate.game.play.proce.result.BuffAnounceResult;
import cate.game.play.proce.result.MissResult;
import cate.game.play.skill.effect.base.HurtHpSE;
import easy.java.dev.note.NoteClass;

@NoteClass("伤害技能效果")
public class 伤害SE extends HurtHpSE {


    @Override
    public void settle(SkillActionCtx action, Fighter target) {
        if (target.isDead()) {
            return;
        }
        AttrPair ap = AttrPair.calc(this, action, target);
        FightAttr actorAttr = ap.actor;
        FightAttr targetAttr = ap.target;
        //伤害格挡检测
        if (avoidHurt(action, target)) {
            return;
        }
        //miss检测
        if (handleMiss(action, target, actorAttr, targetAttr)) {
            return;
        }
        //技能性质
        byte nature = getNature();
        //本次技能初始的血量变化
        double baseDamage = calcHpChange(action, target, actorAttr, targetAttr);

        //真实伤害啥加成都没有
        boolean strike = false;
        if (nature != GDSkill.Nature.REAL) {
            //附加伤害
            baseDamage += this.parent.getExDamage();
            //防御减免
            baseDamage *= calDefRateNew(actorAttr, targetAttr);
            //灵能伤害
            baseDamage += calPsychicDamage(action, actorAttr, targetAttr);
            //伤害增加和减免
            baseDamage *= baseRate(action.getActor(), target, actorAttr, targetAttr, nature);
            //神圣伤害
            baseDamage += calHolyDamage(actorAttr, targetAttr);
            if(!target.buff.containType(GDBuff.Type.免疫暴击)){
                //暴击处理
                double strikeRate = 0.1 + (actorAttr.strike() - targetAttr.strikeAnti()) / GD.W_10000_0;
                strike = Math.random() < strikeRate;
                // 计算实际暴击率
                if (strike) {
                    baseDamage *= Math.max(1.2, 1.5 + (actorAttr.strikeAtt() - targetAttr.strikeAttAnti()) / GD.W_10000_0);
                    action.getMove().stat.strike = true;
                }
            }
            //pvp伤害系数
            if (action.getPlay().isPvP()) {
                baseDamage *= pvpRate(actorAttr, targetAttr);
            } else {
                //pve伤害系数
                baseDamage *= pveRate(actorAttr, targetAttr);
            }
            //伤害豁免
            baseDamage *= calParryRate(action, target, actorAttr, targetAttr);
        }
        //衰减系数
        baseDamage *= 1 + action.getMove().param.getHpChangeRate();
        baseDamage *= 1 + parent.getHpChangeRate(target.getPid());

        if (action.getPlay().isPvP()) {
            baseDamage *= pvpFinalRate(actorAttr, targetAttr);
        }
        //是否无视护盾
        double ignShieldRate = this.parent.ignShieldRate(target.getPid());

        //记录一下原始伤害
        action.getStat().getOrBuildTarget(target.getPid()).originDamage = baseDamage;

        //实际扣除的伤害
        DamageResult damageResult = target.attr.skillHurt(action, action.getActor(), baseDamage, ignShieldRate, strike, GDPlay.HpReason.SKILL_HURT, nature);
        if (damageResult.overFlowDamage > 0) {
            FighterPerformance.recOverFlowDamage(action, action.getActor(), target, damageResult.overFlowDamage);
        }

        final long actualDamage = damageResult.damage;
        //元素伤害
        double elementDamage = calElementDamage(action.getActor().getCamp(), actorAttr, targetAttr);
        if (elementDamage > 0) {
            target.attr.skillHurt(action, action.getActor(), elementDamage, 0d, false, GDPlay.HpReason.ELEMENT, GDSkill.Nature.NULL);
        }
        boolean finalStrike = strike;

        if (finalStrike) {
            FighterPerformance.recStrike(action, action.getActor());
        }

        action.getActor().skill.forHandlers(a -> a.afterOneAttack(action, actualDamage, finalStrike, target));
        action.getActor().buff.forHandlers(a -> a.afterOneAttack(action, nature,actualDamage, finalStrike, target));

        target.skill.forHandlers(a -> a.afterSufferOneAttack(action, actualDamage, finalStrike));
        target.buff.forHandlers(a -> a.afterSufferOneAttack(action, actualDamage, finalStrike));


        if (GDFight.Fighter.isAreaFighter(action.getActor().type)) {
            //属性吸血处理
            handleAttrSuck(action, actorAttr, nature, actualDamage);
        }
        action.getPlay().teamVS.forAreaFighters(a -> a.skill.forHandlers(h -> h.afterOtherOneAttack(action, target, actualDamage, finalStrike)));
    }

    /** 伤害避免检测 */
    private boolean avoidHurt(SkillActionCtx action,Fighter target){
        //免疫检测
        for (BuffHandler handler : target.buff.getHandlers()) {
            if (handler.hurtImmune(action,GDPlay.HpReason.SKILL_HURT)) {
                action.addResult(new BuffAnounceResult().pidSet(target).buffTidSet(handler.buff.tid));
                return true;
            }
        }
        //格挡盾检测
        for (BuffHandler handler : target.buff.getHandlers()) {
            if (handler.hurtBlock(action)) {
                action.addResult(new BuffAnounceResult().pidSet(target).buffTidSet(handler.buff.tid));
                return true;
            }
        }
        return false;
    }

    /** 闪避处理*/
    private boolean handleMiss(SkillActionCtx action, Fighter target, FightAttr actorAttr, FightAttr targetAttr) {
        boolean forceMiss = this.parent.getTargetCtx(target.getPid()).isForceMiss();
        //是否miss
        double hitRate = 1.05 + (actorAttr.hit() - targetAttr.miss()) / GD.W_10000_0;
        hitRate = Math.max(hitRate, 0.1);
        if (forceMiss || Math.random() < 1 - hitRate) {
            MissResult missResult = new MissResult();
            missResult.pidSet(target);
            action.addResult(missResult);
            action.getActor().skill.forHandlers(a->a.onMissAsActor(action, target));
            target.skill.forHandlers(a -> a.onMissAsTarget(action));
            target.buff.forHandlers(a -> a.onMissAsTarget(action));
            return true;
        }
        return false;
    }



    /** 处理属性吸血 */
    private void handleAttrSuck(SkillActionCtx action, FightAttr casterAttr,byte nature, long value) {
        double suckRate = 0;
        switch (nature){
            case GDSkill.Nature.PHY:
                suckRate += casterAttr.suckPhy();
                break;
            case GDSkill.Nature.MAGIC:
                suckRate += casterAttr.suckMagic();
                break;
            default:break;
        }
        double hpSuck = value * (suckRate / GD.W_10000_0);
        hpSuck += casterAttr.suckVal();
        HealResult result = action.getActor().attr.suck(action,action.getActor(),hpSuck, GDPlay.HpReason.ATTR_SUCK);
        if(result.overFlowHeal>0){
            action.getActor().skill.forHandlers(s->s.onOverFlowAttrSuck(action, result.overFlowHeal));
        }
    }

}
